package controllers

import (
	"beego/logic"
	"beego/models"
	"beego/service"
	"encoding/json"
	"fmt"
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/orm"
	"github.com/garyburd/redigo/redis"
	"github.com/goinggo/mapstructure"
	"html"
	"html/template"
	"strconv"
	"time"
)

type AboutController struct {
	beego.Controller
}

func init() {
	// 在初始化控制器时，要注册对应模型结构体，也可以在具体方法内注册
	orm.RegisterModel(new(models.News), new(models.NewsData), new(models.SciLiterature))
}

/**
 * @Title GET
 * @Description 通过ID查询文章html页面
 */

func (c *AboutController) Get() {
	// 获取参数
	//Id, _ := c.Ctx.Input.Param(":id")
	Id, _ := c.GetInt(":id", 1)

	NewsLogic := logic.NewsLogic{}
	news, err, _ := NewsLogic.DetailGet(Id)
	// 查询数据过程中是否有报错
	if err == orm.ErrNoRows {
		fmt.Sprintf("未查询[ID=" + strconv.Itoa(Id) + "]数据记录")
	} else if err == orm.ErrMissPK {
		fmt.Println("找不到主键")
	} else {
		fmt.Sprintf("查询到[ID=" + strconv.Itoa(Id) + "]数据记录")
	}

	// 修改对应文章ID的浏览次数
	news.Hits = news.Hits + 1

	// 更新数据
	OutMysql := orm.NewOrm() //实例化ORM数据连接对象（实例化是面向对象语言的特性，这里借用表达意思）
	qs := OutMysql.QueryTable("hz_1_news")
	qs.Filter("id", Id).Update(orm.Params{"hits": news.Hits})

	// 查询资讯附表文献内容信息
	NewsData := models.NewsData{}
	NewsData.Id = news.Id

	// 查询，赋值到对象变量
	_ = OutMysql.Read(&NewsData)
	//str := template.HTML(newsList.Content)

	str := NewsData.Content
	// 文章总数
	cnt, err := OutMysql.QueryTable("hz_1_news").Count()

	// 对应字段作为模版变量
	c.Data["Title"], c.Data["Description"] = news.Title, news.Description
	c.Data["Inputtime"] = time.Unix(news.Inputtime, 0).Format("2006-01-01 01:01:01") // 时间戳转日期
	c.Data["Hits"], c.Data["TotalCount"] = news.Hits, cnt
	c.Data["Content"] = template.HTML(html.UnescapeString(str)) //将html转成浏览器可以解析的方式

	//数据存储到Redis
	RedisVal := int64(time.Now().Unix())
	redisHost, redisAuth := beego.AppConfig.String("redisHost"), beego.AppConfig.String("redisAuth")
	conRed, err := redis.Dial("tcp", redisHost)
	var Message string
	if err == nil {
		if _, err := conRed.Do("AUTH", redisAuth); err != nil {
			conRed.Close()
			Message = fmt.Sprintf("Redis验证密码失败:%s", err)
		} else {
			if _, err := conRed.Do("Set", "ID:"+strconv.Itoa(Id), RedisVal); err != nil {
				Message = fmt.Sprintf("Redis验证密码失败:%s", err)
			}
		}
	} else {
		Message = fmt.Sprintf("Redis连接失败:%s", err)
	}
	if Message != "" {
		fmt.Println(Message)
		c.Data["ReadTime"] = time.Unix(RedisVal, 0).Format("2006-01-02 15:04:05")
	} else {
		//查看Redis
		redisDate, _ := redis.Int64(conRed.Do("Get", "ID:"+strconv.Itoa(Id)))
		c.Data["ReadTime"] = time.Unix(redisDate, 0).Format("2006-01-02 15:04:05")
	}
	//Map
	var details = make(map[string]interface{})
	details["Name"], details["Age"] = "张三", 18

	//结构体
	var Other struct {
		SiteUrl string
		Year    int
	}
	Other.SiteUrl, Other.Year = "pprof.cn", time.Now().Year()

	c.Data["Details"], c.Data["Other"] = details, Other
	c.TplName = "main/about.tpl"
}

/**
 * @Title Post
 * @Description 通过ID查询文章详情和同栏目文章列表
 */

func (c *AboutController) Post() {
	// JSON数据处理
	ret := service.ReturnMsg{
		Code: 200, Msg: "Success",
	}
	// 过滤请求方法
	Method := c.Ctx.Input.Method()
	if Method != "POST" && Method != "GET" {
		ret.Code, ret.Msg, c.Data["json"] = 10001, "请求方法错误!", ret
	}
	// 获取文章ID
	Id, _ := c.GetInt("id", 1)
	if ret.Code == 200 && Id <= 0 {
		ret.Code, ret.Msg, c.Data["json"] = 10001, "请输入有效参数!", ret
	}

	newsLogic := logic.NewsLogic{}
	newsData, err, cnt := newsLogic.DetailGet(Id)
	// 查询数据过程中是否有报错
	if ret.Code == 200 && err == orm.ErrNoRows {
		ret.Code, ret.Msg, c.Data["json"] = 10002, "Data does not exist.", ret //数据为空
	} else if ret.Code == 200 && err == orm.ErrMissPK {
		ret.Code, ret.Msg, c.Data["json"] = 10003, "Id does not exist.", ret //ID不存在
	}

	if ret.Code == 200 {
		data := make(map[string]interface{})
		//文章详情接口
		data["Detail"], data["TotalCounts"] = newsData, cnt

		//栏目列表
		NewsLogic := logic.NewsLogic{}
		data["List"] = NewsLogic.CateList(newsData.Catid)
		data["LiterData"] = NewsLogic.LiteratureGet()

		//调用公共方法
		data["MapData"], data["SliceData"] = service.MapGet(Id), service.SliceGet(Id)

		ret.Data = data
		c.Data["json"] = ret
	}
	c.ServeJSON() // 对json进行序列化输出
	c.StopRun()
}

/**
 * @Title Custom
 * @Description 框架自动路由
 */

func (c *AboutController) Custom() {
	data := make(map[string]interface{})
	data["totalCounts"] = 5
	data["page"] = 1

	// 声明Map
	dataMap := make(map[string]interface{})
	dataMap["Title"] = "beego"
	dataMap["Id"] = 1

	//var name string = "golang"
	name := "golang"
	fmt.Println(name)

	// 声明结构体
	var dataStruct struct {
		ID    int
		Title string
	}
	if err := mapstructure.Decode(dataMap, &dataStruct); err != nil {
		fmt.Println(err)
	}

	c.Data["json"] = dataStruct
	//fmt.Printf("%T", data)
	//c.Data["json"] = data
	c.ServeJSON() // 对json进行序列化输出
	c.StopRun()
	//c.Ctx.WriteString("/page/about")
}

/**
 * @Title ToMap
 * @Description 通过id传惨，查询对应数据表数据
 */

func (c *AboutController) ToMap() {
	var Id, _ = c.GetInt("id", 2)
	var retTwo []orm.Params
	var mapsList []orm.ParamsList
	var paramsList orm.ParamsList
	newsLogic := logic.NewsLogic{}
	newsData, cnt, retTwo, mapsList, paramsList := newsLogic.DataToMap(Id)
	retData := make(map[string]interface{})
	retData["Data"], retData["TotalCounts"], retData["Values"] = newsData, cnt, retTwo
	retData["ValuesList"], retData["ParamsList"] = mapsList, paramsList
	retData["Id"] = fmt.Sprintf("Controller传过来的参数id=%v,数据类型是%T", Id, Id)
	c.Data["json"] = retData
	c.ServeJSON() // 对json进行序列化输出
	c.StopRun()
}

/**
 * @Title ToMap
 * @Description Join查询
 */
func (c *AboutController) JoinGet() {
	// Session数据处理
	var username = c.GetSession("username")
	if username == nil {
		c.SetSession("username", "zhangsan")
	}

	fmt.Printf("当前月：%v ,当前日：%v \n", time.Now().Month(), time.Now().Day())
	// 列表
	sci := models.SciLiterature{}
	sci.Id = 1

	// 实例化ORM数据连接对象（实例化是面向对象语言的特性，这里借用表达意思）;查询赋值到对象变量
	OutMysql := orm.NewOrm()
	OutMysql.Read(&sci)
	dataMap := make(map[string]interface{})
	dataMap["Sci"], dataMap["Cookie"], dataMap["Username"] = sci, c.Ctx.Input.Cookie("bee_sessId"), c.GetSession("username")

	// JSON数据处理
	ret := service.ReturnMsg{Code: 200, Msg: "Success", Data: dataMap}
	c.Data["json"] = ret
	c.ServeJSON() // 对json进行序列化输出
	c.StopRun()
}

type SciData struct {
	Id       int
	Doi      string
	Pmid     int
	Title    string
	Abstract string
	Authors  []string
	PubType  []string
}

func (c *AboutController) SciGet() {
	Id, _ := c.GetInt(":id", 1)
	sci := models.SciLiterature{}
	sci.Id = Id

	// 实例化ORM数据连接对象（实例化是面向对象语言的特性，这里借用表达意思）;查询赋值到对象变量
	OutMysql := orm.NewOrm()
	_ = OutMysql.Read(&sci)

	sciData := SciData{}
	json.Unmarshal([]byte(sci.Authors), &sciData.Authors)
	json.Unmarshal([]byte(sci.PubType), &sciData.PubType)

	dataMap := make(map[string]interface{})
	sciData.Id, sciData.Doi, sciData.Pmid, sciData.Title, sciData.Abstract = sci.Id, sci.Doi, sci.Pmid, sci.Title, sci.Abstract
	dataMap["sciData"] = sciData
	// JSON数据处理
	ret := service.ReturnMsg{Code: 200, Msg: "Success!", Data: dataMap}
	c.Data["json"] = ret
	c.ServeJSON() // 对json进行序列化输出
	c.StopRun()
}
